﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Collections;
using System.Threading;
using server.filters;
using CommunicationProtocol.filters;
using CommunicationProtocol.dto;
using server.gameLogic;
using server.threadContext;
using System.Collections.ObjectModel;

namespace server
{
    public class Program
    {


        static void Main(string[] args)
        {
            Socket server = new Socket(SocketType.Stream, ProtocolType.Tcp);

            server.Bind(new IPEndPoint(IPAddress.Any, 18899));

            server.Listen(18899);


            ThreadPool.SetMinThreads(2, 2);
            ThreadPool.SetMaxThreads(10, 10);



            

            Console.WriteLine("服务器启动成功");


            while (true)
            {

                

                if (server.Poll(100, SelectMode.SelectRead)) {

                    Socket client = server.Accept();

                    Console.WriteLine($"新客户端 {client.RemoteEndPoint.ToString()} 已连接");

                    AllClientHolder.register(client);
                }


                foreach (KeyValuePair<Socket, ClientMetaData> kvp in AllClientHolder.connectedClients)
                {
                    Socket client = kvp.Key;
                    ClientMetaData value = kvp.Value;

                    if (client.Poll(100, SelectMode.SelectRead)) {

                        if (client.Available == 0)
                        {
                            AllClientHolder.remove(client);
                            continue;
                        }

                        ThreadPool.QueueUserWorkItem(receiveData, kvp);


                    }
                }



                
            }
        }

        static void receiveData(Object  kvp) {

            

            KeyValuePair<Socket, ClientMetaData> clientMetadata = (KeyValuePair<Socket, ClientMetaData>)kvp;

            ClientMetaData clientMetaData = clientMetadata.Value;

            ClientMetaDataContext.set(  clientMetaData);

            try
            {
                Socket clientSocket = clientMetadata.Key;
                var buffer = new byte[clientSocket.Available];

                clientSocket.Receive(buffer);


                new InvocationChain(clientMetaData.inband).invoke(buffer);
            }
            finally {
                // 防止内存泄露
                ClientMetaDataContext.clear();
            }


        }


        static void sendData(Collection<Socket> clients) {

            List<NetFilter> outband = new List<NetFilter>();
            outband.Add(new CommandEncoder());
            outband.Add(new EncodeFrameFilter());

            Task.Run(() => {
                short id = 0;
                byte x = 0;
                byte y = 0;
                while (true)
                {


                    foreach (var socket in clients)
                    {

                        /*if (!socket.Connected) {
                            Console.WriteLine($"{socket.RemoteEndPoint.ToString()}已经被关闭，但其仍然在已连接的客户端列表中");
                            continue;    
                        }*/

                        Console.WriteLine($"向{socket.RemoteEndPoint.ToString()}发送创建一个豌豆射手");
                        List<NetFilter> outbandTemp = new List<NetFilter>(outband);
                        outbandTemp.Add(new SocketSenderFilter(socket));

                        try
                        {
                            new InvocationChain(outbandTemp).invoke(new BaseObject(
                                id,
                                1, // 豌豆射手
                                x,
                                y
                                ));
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("发送数据时遇到异常:" + e.ToString());
                            /*if(connectedClients.TryRemove(socket,out _)){
                                Console.WriteLine($"再次移除客户端{socket.RemoteEndPoint.ToString()}");
                            }*/
                        }

                    }
                    id++;
                    x++;
                    if (x > 9)
                    {
                        x = 0;
                        y++;
                        if (y > 5)
                        {
                            y = 0;
                            x = 0;
                        }
                    }

                    Thread.Sleep(1000);
                    Console.WriteLine($"开始向客户端发送创建豌豆射手位置:{x},{y}   客户端在线数量 {clients.Count}");
                }
            });
        }
    }
}
